<template>
  <div>
    <h1>贪吃蛇</h1>
    <div
      class="box"
      :style="{
        width: widthCount * 10 + 'px',
        height: heightCount * 10 + 'px',
      }"
    >
      <div
        class="coordinate"
        v-for="(coordinate, index) in coordinates"
        :key="index"
        :style="{
          height: coordinateSize + 'px',
          width: coordinateSize + 'px',
          'background-color': getCoordinateBackgroundColor(coordinate),
        }"
      ></div>
    </div>
    <button @click="generateFood">生成食物</button>
    <button @click="snakeAdvance">蛇前进</button>
    <button @click="changeforwardDirection(0)">向左</button>
    <button @click="changeforwardDirection(1)">向上</button>
    <button @click="changeforwardDirection(2)">向右</button>
    <button @click="changeforwardDirection(3)">向下</button>
  </div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { Coordinate } from "./Coordinate";

export default defineComponent({
  data() {
    return {
      coordinateSize: 10,
      widthCount: 50,
      heightCount: 50,
      //坐标系
      coordinates: Array<Coordinate>(),
      //蛇的坐标
      snakeCoordinates: Array<Coordinate>(),
      //食物的坐标
      foodCoordinate: { x: -1, y: -1 },
      //记时
      interval: -1,
      //前进的方向  0 向左 1 向上 2 向右 3向下
      forwardDirection: 2,
    };
  },

  mounted() {
    document.addEventListener("keydown", (e) => {
      if (e.key == "ArrowLeft") {
        this.changeforwardDirection(0);
      } else if (e.key == "ArrowUp") {
        this.changeforwardDirection(1);
      } else if (e.key == "ArrowRight") {
        this.changeforwardDirection(2);
      } else if (e.key == "ArrowDown") {
        this.changeforwardDirection(3);
      }
    });
    this.generateCoordinates();
    this.render();
  },
  methods: {
    render() {
      clearInterval(this.interval);
      this.gennerateSnake();
      this.generateFood();
      // this.snakeAdvance()
    },

    /**
     * 生成坐标
     */
    generateCoordinates() {
      //拿到宽高的数量
      let widthCount = this.widthCount;
      let heightCount = this.heightCount;
      //生成坐标系
      for (let y = 0; y < heightCount; y++) {
        for (let x = 0; x < widthCount; x++) {
          this.coordinates.push({ x: x, y: y });
        }
      }
    },

    /**
     * 生成蛇的坐标
     */
    gennerateSnake() {
      let snakecoordinates = new Array<Coordinate>();
      snakecoordinates.push({ x: 3, y: 6 });
      snakecoordinates.push({ x: 2, y: 6 });
      snakecoordinates.push({ x: 1, y: 6 });
      this.snakeCoordinates = snakecoordinates;
    },

    /**
     * 生成食物
     */
    generateFood() {
      //获取坐标系的长度
      let coordinatesLength = this.coordinates.length;
      //随机生成一个坐标,并判断是否合法
      let isTtLegal = true;
      do {
        //随机生成一个坐标
        let floor = Math.floor(Math.random() * coordinatesLength);
        let foodCoordinate = this.coordinates[floor];
        //判断是否合法，不在蛇所占有的坐标里
        let indexOf = this.indexOfSnakeCoordinates(foodCoordinate);
        isTtLegal = indexOf < 0;
        if (isTtLegal) {
          this.foodCoordinate = foodCoordinate;
        }
      } while (!isTtLegal);
    },
    /**
     * 获取坐标的背景颜色
     */
    getCoordinateBackgroundColor(coordinate: Coordinate): string {
      if (coordinate === this.foodCoordinate) {
        return "red";
      }
      let indexOf = this.indexOfSnakeCoordinates(coordinate);
      if (indexOf == 0) {
        return "black";
      } else if (indexOf > 0) {
        return "blue";
      }
      return "white";
    },
    /**
     * 获取坐标在蛇的位置
     */
    indexOfSnakeCoordinates(coordinate: Coordinate): number {
      let length = this.snakeCoordinates.length;
      for (let index = 0; index < length; index++) {
        let snakeCoordinate = this.snakeCoordinates[index];
        if (
          snakeCoordinate.x === coordinate.x &&
          snakeCoordinate.y === coordinate.y
        ) {
          return index;
        }
      }
      return -1;
    },
    /**
     * 蛇前进 定时改变蛇的位置坐标
     */
    snakeAdvance() {
      this.gennerateSnake();
      this.interval = setInterval(() => {
        let oldSnakeCoordinates = this.snakeCoordinates;
        //获取前进方向 0 向左 1 向上 2 向右 3向下
        let forwardDirection = this.forwardDirection;
        let coordinates = oldSnakeCoordinates[0];
        let newCoordinates;
        switch (forwardDirection) {
          case 0:
            newCoordinates = { x: coordinates.x - 1, y: coordinates.y };
            break;
          case 1:
            newCoordinates = { x: coordinates.x, y: coordinates.y - 1 };
            break;
          case 2:
            newCoordinates = { x: coordinates.x + 1, y: coordinates.y };
            break;
          case 3:
            newCoordinates = { x: coordinates.x, y: coordinates.y + 1 };
            break;
          default:
            return;
        }
        //判断结果
        //1.新的头部是否超出坐标系，失败
        if (
          newCoordinates.x < 0 ||
          newCoordinates.x >= this.widthCount ||
          newCoordinates.y < 0 ||
          newCoordinates.y >= this.heightCount
        ) {
          alert("失败");
          this.render();
          return;
        }
        //2.新的头部在蛇的范围内，失败
        let indexOf = this.indexOfSnakeCoordinates(newCoordinates);
        if (indexOf >= 0) {
          alert("失败");
          this.render();
          return;
        }
        let newSnakeCoordinates = new Array();
        newSnakeCoordinates.push(newCoordinates);
        //判断是否吃到食物,新的坐标等于食物的坐标即为吃到食物
        let isEatFood =
          newCoordinates.x === this.foodCoordinate.x &&
          newCoordinates.y === this.foodCoordinate.y;
          //如果吃到食物，长度增加1，如果未吃到食物，长度不变
        let length = isEatFood
          ? oldSnakeCoordinates.length
          : oldSnakeCoordinates.length - 1;
        for (let index = 0; index < length; index++) {
          newSnakeCoordinates.push(oldSnakeCoordinates[index]);
        }
        //如果吃到食物，生成新的食物
        if (isEatFood) {
          this.generateFood();
        }
        this.snakeCoordinates = newSnakeCoordinates;
      }, 500);
    },
    /**
     * 修改前进的方向
     *
     * @param newForwardDirection 新的方向
     */
    changeforwardDirection(newForwardDirection: number) {
      //判断是否和当前方向相反，如果相反，不处理
      //0 向左 1 向上 2 向右 3向下
      if (newForwardDirection == 0 && this.forwardDirection == 2) {
        return;
      }
      if (newForwardDirection == 1 && this.forwardDirection == 3) {
        return;
      }
      if (newForwardDirection == 2 && this.forwardDirection == 0) {
        return;
      }
      if (newForwardDirection == 3 && this.forwardDirection == 1) {
        return;
      }
      this.forwardDirection = newForwardDirection;
    },
  },
  setup() {},
});
</script>
<style>
.box {
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
  background-color: white;
  border: lightsalmon;
  border-width: 1px;
  border-style: solid;
  margin-left: auto;
  margin-right: auto;
  color: white;
}
.coordinate {
  background-color: white;
  color: black;
}
</style>
